PatchROM assembler
____________________

Starting with PatchROM v0.80, the patch (p) command can be used to assemble 65c816 (SNES)
code and insert it into the ROM.

____________________

I. Variable definition

  To make your asm code easier to read, PatchROM supports variable aliasing. To define
a variable, use the .EQL command:

   variableName .EQL address

  You can also use the .EQL command to define a function address. For example, if the 
hero's health is at $7F2094, the output number function is at $C21028, and the output
character function at $C34083, you might have the following:

   HeroHealth   .EQL $7F2094
   OutputNumber .EQL $C21028
   OutputChar   .EQL $C34083

  Then in your code you can reference the variable by name rather than by address:
 
   lda HeroHealth	; equivalent to: lda $7F2094
   jsl OutputNumber     ; equivalent to: jsl $C21028
   lda #$00             ; space is #$00
   jsr OutputChar       ; equivalent to: jsr $4083 - this is okay because this code
                        ; will be inserted in the $C3 bank. the compiler DOES NOT
                        ; check for this.   

  But the orignal code to fetch the hero's health was "lda $2094". To duplicate this, 
add the following line somewhere before using the variable:

   .ASSUME DBR:$7F

  DBR is the data bank register. The compiler uses a single state variable that is
initially set to $00. Once you change it, it will remain changed until you change it
again. When evaluating variables, if the bank address of the variable matches DBR,
the compiled code will will not include the bank address. 
  The compiler also has a single state variable that determines where immediate operand
are 8- or 16- bit. By default, it is originally set to 16-bit. To change it use:

   .ASSUME MODE:8

  The compiler will automatically update MODE when it sees a sep or rep command.
  
  Some functions do not return to the byte immediately after the jsl. You can represent
these functions by putting the number of skipped bytes after the address:

   GetTableValue .EQL $C17843 (3)

  The skipped bytes are NOT checked when compiling, but when decompiling you might see
something like:
 
   jsl GetTableValue $00,$21,$7E 

  The compile does not support this format. Instead you should use:

   jsl GetTableValue
   .TRIPLE $7E2100	; equivalent to .BYTE $00,$21,$7E

____________________

II. Macros

  To even further ease the readability of code, you can use macros to preform repetitive
tasks. Going back to our above example, let's make a macro for displaying a single
character, which involves loading the character into a and calling OutputChar.

   OutputChar .MACRO	; Since a macro call must start with an underscore, we can use the
    lda ?0              ; same name. ?0 is the first parameter. PatchROM supports ?0 - ?9
    jsr OutputChar      ; Be careful using jsr's in macros 
   .ENDM

  Macros are not evaluated until they are used, so we can use the same macro in 8- or 
16-bit modes. To use our macro in the above code:

   lda HeroHealth	
   jsl OutputNumber     
   _OutputChar #$00     ; equivalent to: lda #$00  jsr $4083  

  Macro parameters are separated by commas. Note that: _MacroName $address,x will evaluate
to two parameters: ?0 = $address and ?1 = x. Also note that macros do not have to have
parameters.

____________________

III. Code blocks

  Most of your code will appear in code blocks. A code block starts with a .ADDRESS and
continues to the next .ADDRESS or the end of the file. Let's look at the code block our
continuing example appears in. There's a lot going on here, but let's look at it a 
little at a time:

   .ASSUME DBR:$7F	  ; Set the data bank register to $7F

   .ADDRESS $C32194 (186) ; This code when compiled cannot be more than 186 bytes and will
                          ; be inserted at $C32194 (masked with the ROM size = $032194). 
                          ; If a maximum size is not specified, 65535 is used.

    pea #$7F7F            ; This is the actual code that sets the data bank register to $7F
    plb                   ; while the ROM is running
    plb

    lda HeroHealth        ; because the databank register is $7F, this becomes: lda $2094

    cmp 0                 ; note: you don't have to use hex. $10, 10h, and 16 are equal

    beq CharIsDead        ; unknown variables are assumed to be unseen labels. if they are
                          ; still unknown at the end of the code block, an error occurs.

    jsl OutputNumber      ; output hero health

   _OutputChar #$00       ; output space

    lda HeroMaxHealth     ; output hero max health
    jsl OutputNumber

    rtl                   ; end of function

CharIsDead:               ; here's the previously unseen label the beq referenced

   _OutputString #$84     ; OutputString is another macro. string #$84 is "DEAD"

    rtl                   ; alternate end of function

   .POINTER 3@$C67243     ; There is a jsl at $C67242, but the code at the address it
                          ; used to point to has been moved here. This will take the <3>
                          ; byte address of the next command and write it at $C67243
                          ; (the operand of the jsl at $C67242). This is equivalent to
                          ; ".PATCH $C67243:BB21C3", but you don't have to remember to
                          ; update the .PATCH statement if the code above changes length.

    pea $7F7F             ; set data bank register to $7F (this is actually a new function)
    plb                   ; this function is identical to the above function, except it 
    plb                   ; uses FriendHealth and FriendMaxHealth. They share the same                         
    lda FriendHealth      ; "DEAD" output code
    cmp 0
    beq CharIsDead
    jsl OutputNumber
   _OutputChar #$00
    lda FriendMaxHealth
    jsl OutputNumber
    rtl                   

  A new .ADDRESS or the end of the file finalizes the compilation of the current code 
block and if it doesn't exceed the maximum size, it is queued to be written to the ROM. 
The entire file must successfully compile or no changes are made to the ROM.

____________________
  
  This document last modified on 12/09/2000 by Brian Weiss